﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;

namespace XLua_Ki
{
    public class Util
    {
        /// 返回游戏资源主AB的根文件夹目录.
        public static string GameDataPath(string gameName)
        {
            return Application.streamingAssetsPath + "/" + gameName + "/";
        }

        /// 打包AB的同时把Lua文件夹完整拷贝过去.
        public static void BuildLuaScripts(string desPath)
        {
            if (!Directory.Exists(AppConst.luaSourcePath))
            {
                Debug.Log(string.Format("Please Creat a packageDirectory : {0}", AppConst.luaSourcePath));
                return;
            }

            string luaScripts_desPath = desPath + "Lua/";
            ResumeFiles(luaScripts_desPath, true, true);
            CopyFiles(AppConst.luaSourcePath, luaScripts_desPath, "*.txt");
        }

        /// 复制文件/文件夹到指定路径
        public static void ShearFiles(string srcPath, string desPath, bool isDirectory = false)
        {
            if (ExistsFile(srcPath, isDirectory))
            {
                if (isDirectory)
                {
                    var desPath_new = desPath + "/" + Util.GetDirectoryName(srcPath) + "/";
                    Util.ResumeFiles(desPath_new, true, true);
                    Util.CopyFiles(srcPath, desPath_new);
                }
                else
                {
                    var desPath_new = desPath + "/" + Util.GetFileName(srcPath);
                    Util.ResumeFiles(desPath_new, false, false);
                    Util.CopyFile(srcPath, desPath_new);
                }
            }
        }

        /// 截取文件夹的名字.
        public static string GetDirectoryName(string dirPath)
        {
            if (ExistsFile(dirPath, true) == false)
            {
                Debug.Log(string.Format("can't find this directory : {0}", dirPath));
                return null;
            }

            int last = dirPath[dirPath.Length - 1] == '/' || dirPath[dirPath.Length - 1] == '\\'
                ? 1 : 0;

            for (int i = dirPath.Length - 2; i >= 0; i--)
            {
                if (dirPath[i] == '/' || dirPath[i] == '\\')
                {
                    var ret = dirPath.Substring(i + 1, (dirPath.Length - last) - (i + 1));
                    return ret;
                }
            }
            return null;
        }

        /// 复制一个文件到某个文件夹下
        public static void CopyFile(string srcPath, string desPath)
        {
            if ((ExistsFile(srcPath, false) == false)) return;
            using (FileStream fs = new FileStream(desPath, FileMode.CreateNew, FileAccess.ReadWrite))
            {
                var bytes = File.ReadAllBytes(srcPath);
                fs.Write(bytes, 0, bytes.Length);
            }
        }

        /// 复制一个文件夹内所有文件到另一个文件夹.
        public static void CopyFiles(string srcPath, string desPath, string searchPatten = null)
        {
            string[] files;
            if (searchPatten == null)
            {
                files = Directory.GetFiles(srcPath);
            }
            else
            {
                files = Directory.GetFiles(srcPath, searchPatten);
            }

            foreach (var item in files)
            {
                if (searchPatten == "*.txt")
                {
                    var str = File.ReadAllText(item);
                    using (TextWriter tw = File.CreateText(desPath + Path.GetFileName(item)))
                    {
                        tw.Write(str);
                    }
                }
                else
                {
                    var name = Path.GetFileName(item);
                    using (FileStream fs = new FileStream(desPath + name, FileMode.CreateNew, FileAccess.ReadWrite))
                    {
                        var bytes = File.ReadAllBytes(item);
                        fs.Write(bytes, 0, bytes.Length);
                    }
                }
            }

            var dirs = Directory.GetDirectories(srcPath);
            foreach (var item in dirs)
            {
                string newdesPath = desPath + "/" + Path.GetFileName(item) + "/";
                Directory.CreateDirectory(newdesPath);
                CopyFiles(item + "/", newdesPath, searchPatten);
            }
        }

        /// 删除文件夹/文件
        public static void ResumeFiles(string desPath, bool isDirectory, bool isCreatNew = false)
        {
            if (isDirectory == true)
            {
                if (!Directory.Exists(desPath))
                {
                    Debug.Log(string.Format("can't find this directory : {0}", desPath));
                    if (isCreatNew == true)
                    {
                        Debug.Log(string.Format("create new directory :{0}", desPath));
                        Directory.CreateDirectory(desPath);
                    }
                }
                else
                {
                    Directory.Delete(desPath, isDirectory);
                    if (isCreatNew == true) Directory.CreateDirectory(desPath);
                }
            }
            else
            {
                if (!File.Exists(desPath))
                {
                    Debug.Log(string.Format("can't find this file : {0}", desPath));
                    if (isCreatNew == true)
                    {
                        Debug.Log(string.Format("create new file :{0}", desPath));
                        File.Create(desPath);
                    }
                }
                else
                {
                    File.Delete(desPath);
                    if (isCreatNew == true) File.Create(desPath);
                }
            }
        }

        /// 是否存在文件夹/文件
        public static bool ExistsFile(string desPath, bool isDirectory)
        {
            if (isDirectory == true)
            {
                return Directory.Exists(desPath);
            }
            else
            {
                return File.Exists(desPath);
            }
        }

        /// 读取txt文本.返回字符串
        public static string ReadTextAsset(string textFilePath)
        {
            return File.ReadAllText(textFilePath);
        }

        /// 从文件夹里获取所有的files文件.[非递归]
        public static string[] GetAllFilesFromPath(string directory_path, string searchPatten = null)
        {
            if (searchPatten == null) return Directory.GetFiles(directory_path);
            else return Directory.GetFiles(directory_path, searchPatten);
        }

        /// 获取上一层文件夹路径
        public static string GetPostDirectoryName(string path, bool isDirectory)
        {
            if (ExistsFile(path, isDirectory))
            {
                if (isDirectory)
                {
                    return Path.GetDirectoryName(path);
                }
                else
                {
                    return GetPostDirectoryName(Path.GetDirectoryName(path), true);
                }
            }
            else
            {
                Debug.Log(string.Format("can't find {0},", path));
                return null;
            }
        }

        /// 保存文本文件到指定路径.
        public static void CreateTextAndWrite(string filepath, string content)
        {
            using (TextWriter tw = File.CreateText(filepath))
            {
                tw.Write(content);
            }
        }

        /// 获取文件名字(无缀名)
        public static string GetFileNameWithoutExtension(string filename)
        {
            return Path.GetFileNameWithoutExtension(filename);
        }

        /// 覆盖写入到文本.
        public static void WriteAllText(string desPath, string content)
        {
            File.WriteAllText(desPath, content);
        }

        /// 获取文件名字.不掉后缀名.
        public static string GetFileName(string filename)
        {
            return Path.GetFileName(filename);
        }

        /// dofile.Lua文件夹内所有的Lua脚本.
        public static void DOLuaFile(string luaPath)
        {
            string[] files = Directory.GetFiles(luaPath, "*.lua.txt");
            foreach (var item in files)
            {
                LuaUtil.CallLuaGlobalMethod(GameManager_Ki.Instance.LuaEnv, "doluafile", item);
            }
            var dirs = Directory.GetDirectories(luaPath);
            for (int i = 0; i < dirs.Length; i++)
            {
                DOLuaFile(dirs[i]);
            }
        }

        /// 计算文件的MD5值
        public static string MD5file(string file)
        {
            try
            {
                FileStream fs = new FileStream(file, FileMode.Open);
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(fs);
                fs.Close();

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("md5file() fail, error:" + ex.Message);
            }
        }

        /// 返回所有文件的"文件相对路径|MD5值".
        public static void GetAllFilesMD5(string filestxt_dirPath, ref string content)
        {
            GetRelativePathsName(filestxt_dirPath, ref content, "", -1);
        }

        /// (PRIVATE) --返回所有文件的"文件相对路径|MD5值". [tempName 默认传"",recursive默认传-1]
        private static void GetRelativePathsName(string last_dirPath, ref string content, string tempName, int recursive)
        {
            string[] hotfixfiles = Util.GetAllFilesFromPath(last_dirPath);

            for (int i = 0; i < hotfixfiles.Length; i++)
            {
                if (Path.GetExtension(hotfixfiles[i]) == ".meta")
                {
                    continue;
                }
                content += tempName + Util.GetFileName(hotfixfiles[i]) + "|" + Util.MD5file(hotfixfiles[i]) + "\r\n";
            }

            var dirs = Directory.GetDirectories(last_dirPath);
            for (int i = 0; i < dirs.Length; i++)
            {
                string lastdir_namr = Util.GetFileNameWithoutExtension(last_dirPath);
                if (tempName.Substring(0, lastdir_namr.Length) != lastdir_namr)
                {
                    recursive++;
                    string[] paths = tempName.Split('/');
                    List<string> parent_path = new List<string>(recursive);
                    for (int j = 0; j < paths.Length; j++)
                    {
                        if (j <= recursive)
                        {
                            parent_path.Add(paths[j]);
                        }
                        else
                        {
                            if (paths[j] == lastdir_namr)
                            {
                                tempName = "";
                                foreach (var item in parent_path)
                                {
                                    tempName += item + "/";
                                }
                                tempName += lastdir_namr + "/";
                                break;
                            }
                        }
                    }
                }

                tempName += Util.GetFileNameWithoutExtension(dirs[i]) + "/";
                GetRelativePathsName(dirs[i], ref content, tempName, recursive);

                recursive = -1;
                tempName = lastdir_namr == "" ? "" : lastdir_namr + "/";
            }
        }

        /// 为文件夹路径添加反斜杠'/'.(如已经有则不添加)
        public static string GetBackslashForDirPath(string dirPath)
        {
            if (!Util.ExistsFile(dirPath, true)) return null;
            string ret = dirPath[dirPath.Length - 1] == '/' || dirPath[dirPath.Length - 1] == '\\' ? dirPath : dirPath + "/";
            return ret;
        }
    }
}
